package com.example.demowx.service;

import com.alibaba.fastjson.JSONObject;
import com.example.demowx.model.AccessToken;
import com.example.demowx.model.BaseMessage;
import com.example.demowx.model.TextMessage;
import com.example.demowx.utils.MyUtil;
import com.thoughtworks.xstream.XStream;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DemoWxService {

    @Value("${demo.appkey}")
    private String appkey;

    @Value("${demo.wxGetTokenUrl}")
    private String wxGetTokenUrl;

    @Value("${demo.appID}")
    private String appId;

    @Value("${demo.appsecret}")
    private String appsecret;

    //用于存储token
    private static AccessToken at;

    /**
     * 向处暴露的获取token的方法
     *
     * @return
     */
    public String getAccessToken() {
        if (at == null || at.isExpired()) {
            getToken();
        }
        return at.getAccessToken();
    }

    private void getToken() {
        //替换访问微信公众号url中的APPID，APPSECRET
        String url = wxGetTokenUrl.replace("APPID", appId).replace("APPSECRET", appsecret);
        //访问微信公众号url获取token
        String tokenStr = MyUtil.get(url);
        JSONObject jsonObject = JSONObject.parseObject(tokenStr);
        String token = jsonObject.getString("access_token");
        String expireIn = jsonObject.getString("expires_in");
        //创建token对象,并存起来。
        at = new AccessToken(token, expireIn);
    }

    public boolean check(String signature, String timestamp, String nonce, String token) {

        //1）将token、timestamp、nonce三个参数进行字典序排序
        String[] str = new String[]{token, timestamp, nonce};
        Arrays.sort(str);
        //2）将三个参数字符串拼接成一个字符串进行sha1加密
        String str2 = str[0] + str[1] + str[2];
        String sha1Str = addSha1(str2);
        //3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
        sha1Str.equals(signature);
        return true;
    }

    private String addSha1(String str2) {


        try {
            //获取一个加密对象
            MessageDigest messageDigest = MessageDigest.getInstance("sha1");
            byte[] digest = messageDigest.digest(str2.getBytes());
            char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            StringBuilder sb = new StringBuilder();
            //处理加密结果
            for (byte b : digest) {
                sb.append(chars[(b >> 4) & 15]);
                sb.append(chars[b & 15]);
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取微信公众号发送的消息
     *
     * @param inputStream 输入流
     * @return
     */
    public Map<String, String> getParams(ServletInputStream inputStream) {
        Map<String, String> map = new HashMap<>();
        SAXReader reader = new SAXReader();
        try {
            //读取输入流，获取文档对象
            Document document = reader.read(inputStream);
            //根据文档对象获取根节点
            Element rootElement = document.getRootElement();
            //获取根节点的所有子节点
            List<Element> elements = rootElement.elements();
            for (Element element : elements) {
                map.put(element.getName(), element.getStringValue());

            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return map;
    }

    public String getRespose(Map<String, String> requestMap) {
        BaseMessage message = null;
        String msgType = requestMap.get("MsgType");
        switch (msgType) {
            case "text":
                //处理文本消息
                message = dealTextMessage(requestMap);
                break;
            case "image":
                break;
            case "voice":
                break;
            case "video":
                break;
            case "music":
                break;
            case "news":
                break;
            case "event":
                message = dealEvent(requestMap);
                break;
            default:
                break;
        }
        //把消息对象处理为xml数据包
        if (message != null) {
            return beanToXml(message);
        }
        return null;
    }

    /**
     * 把实体转换成xml
     *
     * @param message
     * @return
     */
    private String beanToXml(BaseMessage message) {
        XStream xStream = new XStream();
        //设置需要处理XStreamAlias("xml")注释的类
        xStream.processAnnotations(TextMessage.class);
        String s = xStream.toXML(message);
        System.out.println("转换成xml数据\n" + s);
        return s;
    }

    /**
     * 处理文本消息
     *
     * @param requestMap
     * @return
     */
    private BaseMessage dealTextMessage(Map<String, String> requestMap) {
        String msg = requestMap.get("Content");
        if(msg.equals("登录")) {
            String url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx4f7cb53539fe6ad0&redirect_uri=http://2g06z87559.imwork.net/GetUserInfo&response_type=code&scope=snsapi_userinfo#wechat_redirect";
            TextMessage tm = new TextMessage(requestMap, "点击<a href=\""+url+"\">这里</a>登录");
            return tm;
        }
        //调用方法返回聊天的内容
        //String resp = chat(msg);
        TextMessage message = new TextMessage(requestMap, msg);
        return message;
    }

    /**
     * 调用图灵机器人聊天
     *
     * @param msg
     * @return
     */
    private String chat(String msg) {
        String result = null;
        String url = "http://op.juhe.cn/robot/index";//请求接口地址
        Map params = new HashMap();//请求参数
        params.put("key", appkey);//您申请到的本接口专用的APPKEY
        params.put("info", msg);//要发送给机器人的内容，不要超过30个字符
        params.put("dtype", "");//返回的数据的格式，json或xml，默认为json
        params.put("loc", "");//地点，如北京中关村
        params.put("lon", "");//经度，东经116.234632（小数点后保留6位），需要写为116234632
        params.put("lat", "");//纬度，北纬40.234632（小数点后保留6位），需要写为40234632
        params.put("userid", "");//1~32位，此userid针对您自己的每一个用户，用于上下文的关联
        try {
            result = MyUtil.net(url, params, "GET");
            //解析json
            JSONObject jsonObject = JSONObject.parseObject(result);
            //取出error_code
            int code = jsonObject.getInteger("error_code");
            if (code != 0) {
                return null;
            }
            //取出返回的消息的内容
            String resp = jsonObject.getJSONObject("result").getString("text");
            return resp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 处理时间推送
     *
     * @param requestMap
     * @return
     */
    private static BaseMessage dealEvent(Map<String, String> requestMap) {
        String event = requestMap.get("Event");
        switch (event) {
            case "CLICK":
                return dealClick(requestMap);
            case "VIEW":
                return dealView(requestMap);
            default:
                break;

        }
        return null;

    }

    /**
     * 处理view类型的按钮的菜单
     *
     * @param requestMap
     * @return
     */
    private static BaseMessage dealView(Map<String, String> requestMap) {
        return null;
    }

    /**
     * 处理Click菜单
     *
     * @param requestMap
     * @return
     */
    private static BaseMessage dealClick(Map<String, String> requestMap) {
        String key = requestMap.get("EventKey");
        switch (key) {
            //点击一菜单点
            case "1":
                //处理点击了第一个一级菜单
                return new TextMessage(requestMap, "你点了一下第一个一级菜单");
            case "32":
                //处理点击了第三个一级菜单的第二个子菜单
                break;
            default:
                break;
        }
        return null;
    }

    /**
     * 获取关注的用户的基本信息
     *
     * @return by pengyifeng
     */
    public String getUserInfo(String openid) {
        String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
        url = url.replace("ACCESS_TOKEN", getAccessToken()).replace("OPENID", openid);
        String result = MyUtil.get(url);
        return result;
    }

}
